/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.terramagnet.mvcframework.resource.dao;

import org.terramagnet.mvcframework.jdbc.DefaultJdbcTemplate;
import org.terramagnet.mvcframework.resource.ResourceArchive;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;

import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.terramagnet.mvcframework.tools.Paginal;

/**
 *
 * @author terrason
 */
@Repository
public class ResourceDao {

    public static final String cache = "resource";

    @Resource
    private DefaultJdbcTemplate jdbcTemplate;

    public long insert(final ResourceArchive resource) {
        return jdbcTemplate
            .insert("insert into `resource` (`key`,`path`,`file`,`temporary`,create_time) values (?,?,?,1,now())",
                resource.getHash(),
                resource.getUrl(),
                resource.getFile().getAbsolutePath())
            .longValue();
    }

    public void link(long id, String module, String principal) {
        StringBuilder builder = new StringBuilder();
        ArrayList<Object> params = new ArrayList<Object>();

        builder.append("update `resource` set `temporary` = ?");
        params.add(0);

        if (StringUtils.isNotBlank(module)) {
            builder.append(" and `module` = ?");
            params.add(module);
        }
        if (StringUtils.isNotBlank(principal)) {
            builder.append(" and `principal` = ?");
            params.add(principal);
        }

        builder.append(" where id = ?");
        params.add(id);

        jdbcTemplate.update(builder.toString(), params.toArray());
    }

    public void link(String key, String module, String principal) {
        StringBuilder builder = new StringBuilder();
        ArrayList<Object> params = new ArrayList<Object>();

        builder.append("update `resource` set `temporary` = ?");
        params.add(0);

        if (StringUtils.isNotBlank(module)) {
            builder.append(" and `module` = ?");
            params.add(module);
        }
        if (StringUtils.isNotBlank(principal)) {
            builder.append(" and `principal` = ?");
            params.add(principal);
        }

        builder.append(" where `hash_key` = ?");
        params.add(key);

        jdbcTemplate.update(builder.toString(), params.toArray());
    }

    @Cacheable(value = cache, key = "#id")
    public String selectPath(long id) {
        return jdbcTemplate.querySingleObject("select `path` from `resource` where `id`=?", String.class, id);
    }

    @Cacheable(value = cache, key = "#key")
    public ResourceArchive select(String key) {
        return jdbcTemplate.querySingleObject("select id,`path`,`file` from `resource` where `key`=?", new RowMapper<ResourceArchive>() {

            @Override
            public ResourceArchive mapRow(ResultSet rs, int rowNum) throws SQLException {
                ResourceArchive resource = new ResourceArchive(new File(rs.getString("file")), rs.getString("path"));
                resource.setId(rs.getLong("id"));
                return resource;
            }
        }, key);
    }

    @CacheEvict(value = cache, key = "#id")
    public void delete(long id) {
        jdbcTemplate.update("delete from `resource` where `id`=?", id);
    }

    @CacheEvict(value = cache, key = "#key")
    public void delete(String key) {
        jdbcTemplate.update("delete from `resource` where `key`=?", key);
    }

    public void batchDelete(long[] ids) {
        StringBuilder sql = new StringBuilder();
        ArrayList<Long> params = new ArrayList<Long>();
        sql.append("delete from `resource` where `id` in (");
        for (long id : ids) {
            sql.append("?,");
            params.add(id);
        }
        sql.deleteCharAt(sql.length() - 1).append(")");
        jdbcTemplate.update(sql.toString(), params.toArray());
    }

    public void batchDelete(String[] keys) {
        StringBuilder sql = new StringBuilder();
        ArrayList<String> params = new ArrayList<String>();
        sql.append("delete from `resource` where `key` in (");
        for (String key : keys) {
            sql.append("?,");
            params.add(key);
        }
        sql.deleteCharAt(sql.length() - 1).append(")");
        jdbcTemplate.update(sql.toString(), params.toArray());
    }

    /**
     * 分页查询资源表. 查询条件为{@code null}表示忽略该条件。
     *
     * @param temporary 查询条件——是否临时资源
     * @param from 查询条件——资源的创建起始时间（包含）
     * @param to 查询条件——资源的创建结束时间（不包含）
     * @param page 分页参数——页码
     * @param size 分页参数——大小
     * @return 资源列表. 无记录时返回空列表.
     */
    public Paginal<ResourceArchive> selectPaginal(Boolean temporary, Date from, Date to, int page, int size) {
        StringBuilder sql = new StringBuilder();
        ArrayList<Object> params = new ArrayList<Object>();
        sql.append("select id,`path`,`file` from `resource` where 1=1");
        if (temporary != null) {
            sql.append(" and `temporary`=?");
            params.add(temporary);
        }
        if (from != null) {
            sql.append(" and `create_time`>=?");
            params.add(from);
        }
        if (to != null) {
            sql.append(" and `create_time`<?");
            params.add(to);
        }

        sql.append(" order by `create_time` desc");
        params.add((page - 1) * size);
        params.add(size);
        return jdbcTemplate.queryPagination(sql.toString(), new RowMapper<ResourceArchive>() {

            @Override
            public ResourceArchive mapRow(ResultSet rs, int rowNum) throws SQLException {
                ResourceArchive resource = new ResourceArchive(new File(rs.getString("file")), rs.getString("path"));
                resource.setId(rs.getLong("id"));
                return resource;
            }
        }, page, size, params.toArray());
    }
}
